package com.ethink.framework.mybatis.config;

import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

/**
 * @author default
 * @version 1.0.0
 * @ClassName MybatisInterceptor.java
 * @Description
 * @createTime 2022年12月24日 12:34:00
 */
@Slf4j
@Component
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class MybatisInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        String sqlId = mappedStatement.getId();
        log.debug("------sqlId------" + sqlId);
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        Object parameter = invocation.getArgs()[1];
        log.debug("------sqlCommandType------" + sqlCommandType);

        if (parameter == null) {
            return invocation.proceed();
        }
        if (SqlCommandType.INSERT == sqlCommandType || SqlCommandType.UPDATE == sqlCommandType) {
            List<Map<String, Object>> fieldInfo = getFieldInfo(parameter);
            for (Map<String, Object> map : fieldInfo) {
                if (map.get("type").equals(String.class)) {
                    Field field = parameter.getClass().getDeclaredField((String) map.get("name"));
                    field.setAccessible(true);
                    String value = String.valueOf(map.get("value"));
                    if (value != null) {
                        String newValue = value.trim();
                        field.set(parameter, newValue);
                    }else {
                        field.set(parameter,'0');
                    }
                }
            }
        }
        return invocation.proceed();
    }


    public static List<Map<String, Object>> getFieldInfo(Object o) {
        List<Map<String, Object>> list = new ArrayList<>();
        if (ObjectUtil.isEmpty(o)) {
            return null;
        }
        List<Field> fields = new ArrayList<>(Arrays.asList(o.getClass().getDeclaredFields()));
        //未考虑父类
        for (Field field : fields) {
            if (Modifier.isFinal(field.getModifiers())) {
                continue;
            }
            if (ObjectUtil.isEmpty(getFieldValueByName(field.getName(), o))){
                continue;
            }
            Map<String, Object> infoMap = new HashMap<>();
            infoMap.put("type", field.getType());
            infoMap.put("name", field.getName());
            infoMap.put("value", getFieldValueByName(field.getName(), o));
            list.add(infoMap);
        }
        return list;
    }

    public static Object getFieldValueByName(String fileName, Object o) {
        try {
            String firstLetter = fileName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fileName.substring(1);
            Method method = o.getClass().getMethod(getter);
            return method.invoke(o);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

}

